// $codepro.audit.disable numericLiterals
/*
 * Copyright (c) 2011 Team A CS2340. All rights reserved.
 */

package edu.gatech.teama.doctorsoffice.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Server application for DoctorsOffice system.
 * @author Team A
 * @version 1.0
 *
 */
public class Server implements Runnable{ // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString

	/**
	 * Maximum number of connections allowed.
	 */
	public static final int MAX_CONCURRENT_CONNECTIONS = 8;

	/**
	 * Thread pool for <code>ClientMessageHandler</code> instances
	 */
	private final ExecutorService pool;

	/**
	 * Port to listen on
	 */
	private final int port;
	
	/**
	 * Abstract data model to interact with
	 */
	private final DataModel myModel;

	/**
	 * Class's logger
	 */
	private static final Logger LOGGER =
		Logger.getLogger("edu.gatech.teama.doctorsoffice.server.Server");

	static {
		FileHandler fh = null;
		try {
			fh = new FileHandler("application.log");
		} catch (SecurityException e) {
			LOGGER.log(Level.SEVERE,
					"Security Exception creating the logger file handler");
			e.printStackTrace();
		} catch (IOException e) {
			LOGGER.log(Level.SEVERE, "IO Exception creating the logger file handler");
			e.printStackTrace();
		}

		LOGGER.addHandler(fh);
		LOGGER.setLevel(Level.ALL);
	}

	/**
	 * Initialize a new Server with specified port and output filename
	 * @param portP port to listen on
	 * @param filename filename of persistant storage
	 */
	public Server(final int portP, String filename) {
		port = portP;
		pool = Executors.newFixedThreadPool(MAX_CONCURRENT_CONNECTIONS);
		myModel = new SerializedDataModel(filename);
	}

	/**
	 * Execute and begin listening for new connections
	 */
	public void run() {
		final ServerSocket server;
		Socket client = null;

		try {
			LOGGER.info("Starting server");
			server = new ServerSocket(port);

			while (true) { // $codepro.audit.disable constantConditionalExpression, potentialInfiniteLoop
				client = server.accept();

				ClientMessageHandler chandle = new ClientMessageHandler(client, myModel);
				pool.execute(chandle);
			}
		} catch (IOException e) {
			LOGGER.severe("Error in Server Socket accept");
			LOGGER.throwing("Server", "run", e);
		}
	}
	
	/**
	 * main program 
	 * @param args
	 */
	public static void main(String[] args) {
		String filename = "data.dat";
		final Integer port = 4123;
		
		if (args.length == 1) {
			filename = args[0];
		} else if (args.length != 0){
			System.out.println("Usage: java Server [filename]");
			System.exit(1);
		}
		
		//Server srv = new Server(4123, "test.dat");
		final Server srv = new Server(port, filename);
		srv.run();
	}
}
